package com.xiangwei.weixin;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ConnectException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.xiangwei.util.Const;
import com.xiangwei.weixin.entity.AccessToken;
import com.xiangwei.weixin.entity.MaterialPack;
import com.xiangwei.weixin.entity.Media;



/**
 * 公众平台通用接口工具类
 * 
 * @author yanleixin
 * @date 2015-6-26
 */
public class WeixinUtil {
	private static final Logger logger = LoggerFactory
			.getLogger(WeixinUtil.class);
	/**
	 * 发起https请求并获取结果
	 * 
	 * @param requestUrl 请求地址
	 * @param requestMethod 请求方式（GET、POST）
	 * @param outputStr 提交的数据
	 * @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)
	 */
	public static JSONObject httpsRequest(String requestUrl, String requestMethod, String outputStr) {
		JSONObject jsonObject = null;
		StringBuffer buffer = new StringBuffer();
		InputStream inputStream = null;
		InputStreamReader inputStreamReader = null;
		BufferedReader bufferedReader = null;
		HttpsURLConnection httpUrlConn = null;
		try {
			// 创建SSLContext对象，并使用我们指定的信任管理器初始化
			TrustManager[] tm = { new MyX509TrustManager() };
			SSLContext sslContext = SSLContext.getInstance("SSLv3", "SunJSSE");
			sslContext.init(null, tm, new java.security.SecureRandom());
			// 从上述SSLContext对象中得到SSLSocketFactory对象
			SSLSocketFactory ssf = sslContext.getSocketFactory();

			URL url = new URL(requestUrl);
			httpUrlConn = (HttpsURLConnection) url.openConnection();
			httpUrlConn.setSSLSocketFactory(ssf);
			httpUrlConn.setDoOutput(true);
			httpUrlConn.setDoInput(true);
			httpUrlConn.setUseCaches(false);
			// 设置请求方式（GET/POST）
			httpUrlConn.setRequestMethod(requestMethod);
			if (Const.Common.PORTAL_WEIXIN_GET.equalsIgnoreCase(requestMethod))
				httpUrlConn.connect();
			

			// 当有数据需要提交时
			if (null != outputStr) {
				OutputStream outputStream = httpUrlConn.getOutputStream();
//				 注意编码格式，防止中文乱码
				outputStream.write(outputStr.getBytes("UTF-8"));
				outputStream.close();
			}

			// 将返回的输入流转换成字符串
			inputStream = httpUrlConn.getInputStream();
			inputStreamReader = new InputStreamReader(inputStream, "utf-8");
			bufferedReader = new BufferedReader(inputStreamReader);

			String str = null;
			while ((str = bufferedReader.readLine()) != null) {
				buffer.append(str);
			}
			inputStream = null;
			jsonObject = JSONObject.parseObject(buffer.toString());
		} catch (ConnectException ce) {
			ce.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			httpUrlConn.disconnect();
			// 释放资源
			try {
				bufferedReader.close();
				inputStreamReader.close();
				inputStream.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return jsonObject;
	}
	
	/**
	 * 发起http请求并获取结果
	 * 
	 * @param requestUrl 请求地址
	 * @param requestMethod 请求方式（GET、POST）
	 * @param outputStr 提交的数据
	 * @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)
	 */
	public static JSONObject httpRequest(String requestUrl, String requestMethod, String outputStr) {
		JSONObject jsonObject = null;
		InputStream is = null;
		ByteArrayOutputStream os = null;
		try {
			URL url = new URL(requestUrl);
			os = new ByteArrayOutputStream();
			HttpURLConnection con = (HttpURLConnection) url.openConnection();
			con.setRequestMethod(requestMethod);
			con.setDoOutput(true);
			con.setDoInput(true);
			con.connect();

			if (outputStr != null) {
				con.getOutputStream().write(outputStr.getBytes("utf-8"));
			}

			is = con.getInputStream();
			byte[] buffer = new byte[2014];
			int len = is.read(buffer);
			while (len > 0) {
				os.write(buffer, 0, len);
				len = is.read(buffer);
			}
			
			String result = new String(os.toByteArray(), "utf-8");
			jsonObject = JSONObject.parseObject(result);
		} catch (Exception e) {
			logger.error("发送HTTP POST 请求异常！", e);
		} finally {
			try {
				os.close();
				is.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return jsonObject;
	}
	
	public final static String access_token_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";

	/**
	 * 获取access_token
	 * 
	 * @param appid 凭证
	 * @param appsecret 密钥
	 * @return
	 */
	public static AccessToken getAccessToken(String appid, String appsecret) {
		AccessToken accessToken = null;

		String requestUrl = access_token_url.replace("APPID", appid).replace("APPSECRET", appsecret);
		JSONObject jsonObject = httpRequest(requestUrl, Const.Common.PORTAL_WEIXIN_GET, null);
		// 如果请求成功
		if (null != jsonObject) {
			try {
				accessToken = new AccessToken();
				accessToken.setToken(jsonObject.getString("access_token"));
				accessToken.setExpiresIn(jsonObject.getIntValue("expires_in"));
			} catch (JSONException e) {
				accessToken = null;
				// 获取token失败
				e.printStackTrace();
			}
		}
		return accessToken;
	}
	
	// 菜单创建（POST） 限100（次/天）
	public static String menu_create_url = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN";

	/**
	 * 创建菜单
	 * 
	 * @param menu 菜单实例
	 * @param accessToken 有效的access_token
	 * @return 0表示成功，其他值表示失败
	 */
	public static int createMenu(Object menu, String accessToken) {
		int result = 0;

		// 拼装创建菜单的url
		String url = menu_create_url.replace("ACCESS_TOKEN", accessToken);
		// 将菜单对象转换成json字符串
//		String jsonMenu = JSONObject.fromObject(menu).toString();
		// 调用接口创建菜单
		JSONObject jsonObject = httpRequest(url, Const.Common.PORTAL_WEIXIN_POST, menu.toString());
		if (null != jsonObject) {
			if (0 != jsonObject.getIntValue("errcode")) {
				result = jsonObject.getIntValue("errcode");
			}
		}
		return result;
	}
	//微信jssdk的ticket请求URL地址
	private final static String weixin_jssdk_ticket_url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi"; 
	/**
	 * 获取jssdk 的ticket
	 * 
	 * @param appid
	 * @param appsecret
	 * 
	 * @return 返回jssdk的ticket
	 * 
	 * */
	
	public static String getJSSDKTicket(String accessToken){
		String ticket = "";
		String url = weixin_jssdk_ticket_url.replace("ACCESS_TOKEN", accessToken);
		
		JSONObject jsonObject = httpRequest(url, Const.Common.PORTAL_WEIXIN_GET, "");
		
		if (jsonObject!=null) {
			try {
				ticket = jsonObject.getString("ticket");
			} catch (Exception e) {
				logger.error(e.toString(),e);
			}
		}
		
		return ticket;
	}
	private final static String weixin_articles_add = "https://api.weixin.qq.com/cgi-bin/material/add_news?access_token=ACCESS_TOKEN";
	/**
	 * 新增永久素材
	 * @param accessToken
	 * @param mp
	 * 
	 * @return  返回新增的图文消息素材的media_id
	 * 
	 * */
	public static String getArticles(String accessToken,MaterialPack mp){
		String media_id = "";
		String url = weixin_articles_add.replace("ACCESS_TOKEN", accessToken);
		String string = JSONObject.toJSONString(mp);
		JSONObject object = httpRequest(url, Const.Common.PORTAL_WEIXIN_POST, string);
		if (object!=null) {
			try {
				media_id = object.getString("media_id");
			} catch (Exception e) {
				media_id = "0";
			}
		}
		return media_id;
	}
	
	private static final String weixin_articles_delete="https://api.weixin.qq.com/cgi-bin/material/del_material?access_token=ACCESS_TOKEN";
	/**
	 * 删除永久素材
	 * 
	 * @param accessToken
	 * @param media_id
	 * 
	 * @return 成功之后返回的结果
	 * 
	 * */
	public static String getDelArticles(String accessToken,Media media){
		String url = weixin_articles_delete.replace("ACCESS_TOKEN", accessToken);
		String string = JSONObject.toJSONString(media);
		JSONObject object = httpRequest(url, Const.Common.PORTAL_WEIXIN_POST, string);
		String errcode = object.getString("errcode");
		if (errcode.equals("0")) {
			return "SUCCESS";
		}
		return "ERROR";
	}

	
	private static final String weixin_web_access_token = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
	
	/**
	 * 获取web_access_token
	 * 返回json
	 * */
	public static JSONObject webAccessToken(String appid,String appsecret,String code){
		logger.info("code:"+code);
		String url = weixin_web_access_token.replace("APPID", appid).replace("SECRET", appsecret).replace("CODE", code);
		JSONObject json = httpRequest(url, Const.Common.PORTAL_WEIXIN_GET, "");
		return json;
	}
	
	private static final String weixin_user_info = "https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN";
	
	/**
	 * 获取微信用户个人信息
	 * */
	public static JSONObject userInfo(String access_tonken,String openid){
		String url = weixin_user_info.replace("ACCESS_TOKEN", access_tonken).replace("OPENID", openid);
		JSONObject JSON = httpRequest(url, Const.Common.PORTAL_WEIXIN_GET, "");
		return JSON;
	}
	/**
	 * 获取公众号全部信息
	 * */
	private static final String weixin_user_allinfo = "https://api.weixin.qq.com/cgi-bin/user/get?access_token=ACCESS_TOKEN&next_openid=NEXT_OPENID";
	
	public static JSONObject allUserinfo(String access_token,String next_openid){
		String url = weixin_user_allinfo.replace("ACCESS_TOKEN", access_token).replace("NEXT_OPENID", next_openid);
		JSONObject json = httpRequest(url, Const.Common.PORTAL_WEIXIN_GET, "");
		return json;
	}
	private static final String weixin_qrCode_url = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=TOKEN";
	/**
	 * 创建微信永久二维码
	 * */
	public static JSONObject weixinQrCode(String appid,String appsecrt,String scene_str){
		AccessToken token = getAccessToken(appid, appsecrt);
		String url = weixin_qrCode_url.replace("TOKEN", token.getToken());
		String jsonObject = getweixinQrCodeJson(scene_str);
		JSONObject object = httpRequest(url, Const.Common.PORTAL_WEIXIN_POST, jsonObject);
		return object;
	}
	private static final String weixin_template = "https://api.weixin.qq.com/cgi-bin/template/api_add_template?access_token=ACCESS_TOKEN";
	/**
	 * 获得模版消息
	 * */
	public static JSONObject getTemplate(String templateIdShort,String accessToken){
		String url = weixin_template.replace("ACCESS_TOKEN", accessToken);
		JSONObject object = httpRequest(url, "POST", templateIdShort);
		return object;
	}
	private static final String weixin_send_template = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=ACCESS_TOKEN";
	/**
	 * 发送模版消息
	 * */
	public static JSONObject sendTemplate(String accessToken,String properties){
		logger.info("WeixinUtil sendTemplate accessToken:"+accessToken+",properties:"+properties);
		String url = weixin_send_template.replace("ACCESS_TOKEN", accessToken);
		JSONObject object = httpRequest(url, "POST", properties);
		logger.info(object.toString());
		return object;
	}
	
	private static String getweixinQrCodeJson(String scene_str){
		HashMap<String,Object> map = new HashMap<String, Object>();
		map.put("action_name", "QR_LIMIT_STR_SCENE");
		Map<String,Object> map2 = new HashMap<String, Object>();
		Map<String,Object> map3 = new HashMap<String, Object>();
		map3.put("scene_str", scene_str);
		map2.put("scene", map3);
		map.put("action_info",map2);
		JSONObject object = new JSONObject(map);
		return object.toJSONString();
	}
	
}